"""
工作流管理器

负责工作流的创建、执行、监控和管理。
"""

from typing import Dict, List, Any, Optional, Callable, Set
from datetime import datetime, timedelta
import asyncio
import uuid
from collections import defaultdict

from .workflow_types import (
    WorkflowDefinition,
    WorkflowInstance,
    WorkflowContext,
    WorkflowStatus,
    WorkflowNode,
    WorkflowEdge,
    NodeType,
    EdgeType,
    WorkflowExecutor,
    WorkflowListener
)
from ..coordination.coordination_engine import CoordinationEngine
from ..agents.agent_registry import AgentRegistry


class WorkflowManager:
    """
    工作流管理器
    
    负责工作流的生命周期管理，包括创建、执行、监控、暂停、恢复和取消。
    """
    
    def __init__(
        self,
        coordination_engine: Optional[CoordinationEngine] = None,
        agent_registry: Optional[AgentRegistry] = None
    ):
        """
        初始化工作流管理器
        
        Args:
            coordination_engine: 协调引擎
            agent_registry: 智能体注册表
        """
        self.coordination_engine = coordination_engine
        self.agent_registry = agent_registry
        
        # 工作流定义存储
        self.workflow_definitions: Dict[str, WorkflowDefinition] = {}
        
        # 运行中的工作流实例
        self.running_instances: Dict[str, WorkflowInstance] = {}
        
        # 已完成的工作流实例（最近1000个）
        self.completed_instances: Dict[str, WorkflowInstance] = {}
        self._max_completed_instances = 1000
        
        # 执行器注册表
        self.executors: Dict[str, WorkflowExecutor] = {}
        
        # 监听器列表
        self.listeners: List[WorkflowListener] = []
        
        # 调度队列
        self.pending_queue: List[WorkflowInstance] = []
        self.scheduled_queue: List[WorkflowInstance] = []
        
        # 执行控制
        self._running = False
        self._max_concurrent_instances = 10
        self._execution_task: Optional[asyncio.Task] = None
        
        # 统计信息
        self.stats = {
            "total_executed": 0,
            "total_completed": 0,
            "total_failed": 0,
            "total_cancelled": 0,
            "average_execution_time": timedelta(0)
        }
    
    async def initialize(self) -> None:
        """初始化工作流管理器（标准生命周期方法）"""
        await self.start()
    
    async def close(self) -> None:
        """关闭工作流管理器（标准生命周期方法）"""
        await self.stop()
    
    async def start(self) -> None:
        """启动工作流管理器"""
        if self._running:
            return
        
        self._running = True
        self._execution_task = asyncio.create_task(self._execution_loop())
    
    async def stop(self) -> None:
        """停止工作流管理器"""
        self._running = False
        
        if self._execution_task:
            self._execution_task.cancel()
            try:
                await self._execution_task
            except asyncio.CancelledError:
                pass
        
        # 取消所有运行中的实例
        for instance in list(self.running_instances.values()):
            await self.cancel_instance(instance.instance_id)
    
    def register_workflow_definition(self, definition: WorkflowDefinition) -> None:
        """
        注册工作流定义
        
        Args:
            definition: 工作流定义
        """
        # 验证工作流定义
        errors = definition.validate()
        if errors:
            raise ValueError(f"工作流定义验证失败: {errors}")
        
        self.workflow_definitions[definition.workflow_id] = definition
    
    def get_workflow_definition(self, workflow_id: str) -> Optional[WorkflowDefinition]:
        """
        获取工作流定义
        
        Args:
            workflow_id: 工作流ID
            
        Returns:
            工作流定义
        """
        return self.workflow_definitions.get(workflow_id)
    
    def list_workflow_definitions(self) -> List[WorkflowDefinition]:
        """获取所有工作流定义"""
        return list(self.workflow_definitions.values())
    
    def register_executor(self, name: str, executor: WorkflowExecutor) -> None:
        """
        注册执行器
        
        Args:
            name: 执行器名称
            executor: 执行器实例
        """
        self.executors[name] = executor
    
    def add_listener(self, listener: WorkflowListener) -> None:
        """
        添加监听器
        
        Args:
            listener: 监听器实例
        """
        self.listeners.append(listener)
    
    async def create_instance(
        self,
        workflow_id: str,
        input_data: Optional[Dict[str, Any]] = None,
        instance_id: Optional[str] = None,
        priority: int = 0,
        scheduled_at: Optional[datetime] = None,
        **kwargs
    ) -> WorkflowInstance:
        """
        创建工作流实例
        
        Args:
            workflow_id: 工作流定义ID
            input_data: 输入数据
            instance_id: 实例ID（可选）
            priority: 优先级
            scheduled_at: 调度时间
            **kwargs: 其他参数
            
        Returns:
            工作流实例
        """
        definition = self.get_workflow_definition(workflow_id)
        if not definition:
            raise ValueError(f"工作流定义不存在: {workflow_id}")
        
        instance = WorkflowInstance.create(
            workflow_definition=definition,
            input_data=input_data,
            instance_id=instance_id,
            priority=priority,
            scheduled_at=scheduled_at,
            **kwargs
        )
        
        # 添加到调度队列
        if scheduled_at and scheduled_at > datetime.now():
            self.scheduled_queue.append(instance)
            self.scheduled_queue.sort(key=lambda x: x.scheduled_at or datetime.min)
        else:
            self.pending_queue.append(instance)
            self.pending_queue.sort(key=lambda x: x.priority, reverse=True)
        
        return instance
    
    async def execute_instance(self, instance_id: str) -> WorkflowInstance:
        """
        执行工作流实例
        
        Args:
            instance_id: 实例ID
            
        Returns:
            工作流实例
        """
        instance = self._find_instance(instance_id)
        if not instance:
            raise ValueError(f"工作流实例不存在: {instance_id}")
        
        if instance.context.status != WorkflowStatus.PENDING:
            raise ValueError(f"工作流实例状态不正确: {instance.context.status}")
        
        # 移动到运行队列
        self._remove_from_queues(instance)
        self.running_instances[instance_id] = instance
        
        # 开始执行
        await self._execute_instance_internal(instance)
        
        return instance
    
    async def pause_instance(self, instance_id: str) -> None:
        """
        暂停工作流实例
        
        Args:
            instance_id: 实例ID
        """
        instance = self.running_instances.get(instance_id)
        if not instance:
            raise ValueError(f"运行中的工作流实例不存在: {instance_id}")
        
        instance.context.status = WorkflowStatus.PAUSED
        instance.context.add_execution_record({
            "action": "paused",
            "node_id": instance.context.current_node_id
        })
    
    async def resume_instance(self, instance_id: str) -> None:
        """
        恢复工作流实例
        
        Args:
            instance_id: 实例ID
        """
        instance = self.running_instances.get(instance_id)
        if not instance:
            raise ValueError(f"运行中的工作流实例不存在: {instance_id}")
        
        if instance.context.status != WorkflowStatus.PAUSED:
            raise ValueError(f"工作流实例状态不正确: {instance.context.status}")
        
        instance.context.status = WorkflowStatus.RUNNING
        instance.context.add_execution_record({
            "action": "resumed",
            "node_id": instance.context.current_node_id
        })
    
    async def cancel_instance(self, instance_id: str) -> None:
        """
        取消工作流实例
        
        Args:
            instance_id: 实例ID
        """
        instance = self._find_instance(instance_id)
        if not instance:
            raise ValueError(f"工作流实例不存在: {instance_id}")
        
        # 更新状态
        instance.context.status = WorkflowStatus.CANCELLED
        instance.context.completed_at = datetime.now()
        instance.context.add_execution_record({
            "action": "cancelled",
            "node_id": instance.context.current_node_id
        })
        
        # 移动到已完成队列
        self._remove_from_queues(instance)
        if instance_id in self.running_instances:
            del self.running_instances[instance_id]
        
        self._add_to_completed(instance)
        
        # 通知监听器
        for listener in self.listeners:
            try:
                await listener.on_workflow_failed(instance, Exception("工作流被取消"))
            except Exception:
                pass  # 忽略监听器错误
        
        # 更新统计
        self.stats["total_cancelled"] += 1
    
    def get_instance(self, instance_id: str) -> Optional[WorkflowInstance]:
        """
        获取工作流实例
        
        Args:
            instance_id: 实例ID
            
        Returns:
            工作流实例
        """
        return self._find_instance(instance_id)
    
    def list_running_instances(self) -> List[WorkflowInstance]:
        """获取所有运行中的实例"""
        return list(self.running_instances.values())
    
    def list_pending_instances(self) -> List[WorkflowInstance]:
        """获取所有待执行的实例"""
        return self.pending_queue.copy()
    
    def list_scheduled_instances(self) -> List[WorkflowInstance]:
        """获取所有已调度的实例"""
        return self.scheduled_queue.copy()
    
    def get_stats(self) -> Dict[str, Any]:
        """获取统计信息"""
        return {
            **self.stats,
            "running_instances": len(self.running_instances),
            "pending_instances": len(self.pending_queue),
            "scheduled_instances": len(self.scheduled_queue),
            "completed_instances": len(self.completed_instances)
        }
    
    async def _execution_loop(self) -> None:
        """执行循环"""
        while self._running:
            try:
                # 处理调度队列
                await self._process_scheduled_queue()
                
                # 处理待执行队列
                await self._process_pending_queue()
                
                # 检查超时实例
                await self._check_timeout_instances()
                
                # 短暂休眠
                await asyncio.sleep(1)
                
            except Exception as e:
                # 记录错误但继续运行
                print(f"执行循环错误: {e}")
                await asyncio.sleep(5)
    
    async def _process_scheduled_queue(self) -> None:
        """处理调度队列"""
        now = datetime.now()
        ready_instances = []
        
        for instance in self.scheduled_queue:
            if instance.scheduled_at and instance.scheduled_at <= now:
                ready_instances.append(instance)
        
        for instance in ready_instances:
            self.scheduled_queue.remove(instance)
            self.pending_queue.append(instance)
        
        # 重新排序待执行队列
        self.pending_queue.sort(key=lambda x: x.priority, reverse=True)
    
    async def _process_pending_queue(self) -> None:
        """处理待执行队列"""
        if len(self.running_instances) >= self._max_concurrent_instances:
            return
        
        if not self.pending_queue:
            return
        
        # 获取最高优先级的实例
        instance = self.pending_queue.pop(0)
        
        # 开始执行
        self.running_instances[instance.instance_id] = instance
        asyncio.create_task(self._execute_instance_internal(instance))
    
    async def _check_timeout_instances(self) -> None:
        """检查超时实例"""
        now = datetime.now()
        timeout_instances = []
        
        for instance in self.running_instances.values():
            if instance.max_execution_time and instance.context.started_at:
                elapsed = now - instance.context.started_at
                if elapsed > instance.max_execution_time:
                    timeout_instances.append(instance)
        
        for instance in timeout_instances:
            instance.context.status = WorkflowStatus.TIMEOUT
            instance.context.completed_at = now
            instance.context.error_message = "执行超时"
            
            await self._complete_instance(instance)
    
    async def _execute_instance_internal(self, instance: WorkflowInstance) -> None:
        """内部执行实例"""
        try:
            # 更新状态
            instance.context.status = WorkflowStatus.RUNNING
            instance.context.started_at = datetime.now()
            instance.context.current_node_id = instance.workflow_definition.start_node_id
            
            # 通知监听器
            for listener in self.listeners:
                try:
                    await listener.on_workflow_started(instance)
                except Exception:
                    pass
            
            # 执行工作流
            await self._execute_workflow(instance)
            
            # 标记完成
            if instance.context.status == WorkflowStatus.RUNNING:
                instance.context.status = WorkflowStatus.COMPLETED
                instance.context.completed_at = datetime.now()
            
            await self._complete_instance(instance)
            
        except Exception as e:
            # 处理执行错误
            instance.context.status = WorkflowStatus.FAILED
            instance.context.completed_at = datetime.now()
            instance.context.error_message = str(e)
            instance.context.error_details = {"exception": type(e).__name__}
            
            # 通知监听器
            for listener in self.listeners:
                try:
                    await listener.on_workflow_failed(instance, e)
                except Exception:
                    pass
            
            await self._complete_instance(instance)
    
    async def _execute_workflow(self, instance: WorkflowInstance) -> None:
        """执行工作流"""
        current_node_id = instance.context.current_node_id
        visited_nodes: Set[str] = set()
        
        while current_node_id and instance.context.status == WorkflowStatus.RUNNING:
            # 防止无限循环
            if current_node_id in visited_nodes:
                # 对于循环节点，允许重复访问
                node = instance.workflow_definition.get_node(current_node_id)
                if node and node.node_type != NodeType.LOOP:
                    break
            
            visited_nodes.add(current_node_id)
            
            # 获取当前节点
            node = instance.workflow_definition.get_node(current_node_id)
            if not node:
                raise ValueError(f"节点不存在: {current_node_id}")
            
            # 执行节点
            next_node_id = await self._execute_node(instance, node)
            
            # 更新当前节点
            current_node_id = next_node_id
            instance.context.current_node_id = current_node_id
            
            # 检查是否到达结束节点
            if current_node_id in instance.workflow_definition.end_node_ids:
                break
    
    async def _execute_node(self, instance: WorkflowInstance, node: WorkflowNode) -> Optional[str]:
        """执行单个节点"""
        try:
            # 通知监听器
            for listener in self.listeners:
                try:
                    await listener.on_node_started(instance, node)
                except Exception:
                    pass
            
            # 记录执行开始
            instance.context.add_execution_record({
                "action": "node_started",
                "node_id": node.node_id,
                "node_type": node.node_type.value
            })
            
            result = None
            
            # 根据节点类型执行
            if node.node_type == NodeType.START:
                result = await self._execute_start_node(instance, node)
            elif node.node_type == NodeType.END:
                result = await self._execute_end_node(instance, node)
            elif node.node_type == NodeType.TASK:
                result = await self._execute_task_node(instance, node)
            elif node.node_type == NodeType.DECISION:
                result = await self._execute_decision_node(instance, node)
            elif node.node_type == NodeType.PARALLEL:
                result = await self._execute_parallel_node(instance, node)
            elif node.node_type == NodeType.CONDITION:
                result = await self._execute_condition_node(instance, node)
            elif node.node_type == NodeType.LOOP:
                result = await self._execute_loop_node(instance, node)
            else:
                raise ValueError(f"不支持的节点类型: {node.node_type}")
            
            # 保存结果
            instance.context.set_node_result(node.node_id, result)
            
            # 通知监听器
            for listener in self.listeners:
                try:
                    await listener.on_node_completed(instance, node, result)
                except Exception:
                    pass
            
            # 记录执行完成
            instance.context.add_execution_record({
                "action": "node_completed",
                "node_id": node.node_id,
                "result": result
            })
            
            # 获取下一个节点
            return await self._get_next_node(instance, node, result)
            
        except Exception as e:
            # 通知监听器
            for listener in self.listeners:
                try:
                    await listener.on_node_failed(instance, node, e)
                except Exception:
                    pass
            
            # 记录执行失败
            instance.context.add_execution_record({
                "action": "node_failed",
                "node_id": node.node_id,
                "error": str(e)
            })
            
            raise
    
    async def _execute_start_node(self, instance: WorkflowInstance, node: WorkflowNode) -> Any:
        """执行开始节点"""
        return instance.context.input_data
    
    async def _execute_end_node(self, instance: WorkflowInstance, node: WorkflowNode) -> Any:
        """执行结束节点"""
        return instance.context.variables
    
    async def _execute_task_node(self, instance: WorkflowInstance, node: WorkflowNode) -> Any:
        """执行任务节点"""
        if not node.executor:
            raise ValueError(f"任务节点缺少执行器: {node.node_id}")
        
        executor = self.executors.get(node.executor)
        if not executor:
            raise ValueError(f"执行器不存在: {node.executor}")
        
        return await executor.execute_node(node, instance.context)
    
    async def _execute_decision_node(self, instance: WorkflowInstance, node: WorkflowNode) -> Any:
        """执行决策节点"""
        # 评估所有条件
        results = {}
        for condition in node.conditions:
            condition_expr = condition.get("expression")
            if condition_expr:
                executor = self.executors.get("default")
                if executor:
                    result = await executor.evaluate_condition(condition_expr, instance.context)
                    results[condition.get("name", condition_expr)] = result
        
        return results
    
    async def _execute_parallel_node(self, instance: WorkflowInstance, node: WorkflowNode) -> Any:
        """执行并行节点"""
        # 并行执行所有分支
        tasks = []
        for branch_id in node.parallel_branches:
            branch_node = instance.workflow_definition.get_node(branch_id)
            if branch_node:
                task = asyncio.create_task(self._execute_node(instance, branch_node))
                tasks.append(task)
        
        if tasks:
            results = await asyncio.gather(*tasks, return_exceptions=True)
            return results
        
        return []
    
    async def _execute_condition_node(self, instance: WorkflowInstance, node: WorkflowNode) -> Any:
        """执行条件节点"""
        if not node.conditions:
            return True
        
        # 评估第一个条件
        condition = node.conditions[0]
        condition_expr = condition.get("expression")
        if condition_expr:
            executor = self.executors.get("default")
            if executor:
                return await executor.evaluate_condition(condition_expr, instance.context)
        
        return False
    
    async def _execute_loop_node(self, instance: WorkflowInstance, node: WorkflowNode) -> Any:
        """执行循环节点"""
        results = []
        iteration = 0
        
        while iteration < node.max_iterations:
            # 检查循环条件
            if node.loop_condition:
                executor = self.executors.get("default")
                if executor:
                    should_continue = await executor.evaluate_condition(
                        node.loop_condition, 
                        instance.context
                    )
                    if not should_continue:
                        break
            
            # 执行循环体（假设第一个分支是循环体）
            if node.parallel_branches:
                branch_id = node.parallel_branches[0]
                branch_node = instance.workflow_definition.get_node(branch_id)
                if branch_node:
                    result = await self._execute_node(instance, branch_node)
                    results.append(result)
            
            iteration += 1
        
        return results
    
    async def _get_next_node(self, instance: WorkflowInstance, node: WorkflowNode, result: Any) -> Optional[str]:
        """获取下一个节点"""
        edges = instance.workflow_definition.get_edges_from_node(node.node_id)
        
        if not edges:
            return None
        
        # 对于单一出边，直接返回
        if len(edges) == 1:
            return edges[0].target_node_id
        
        # 对于多个出边，根据条件选择
        for edge in edges:
            if edge.condition:
                executor = self.executors.get("default")
                if executor:
                    condition_result = await executor.evaluate_condition(
                        edge.condition, 
                        instance.context
                    )
                    if condition_result:
                        return edge.target_node_id
        
        # 如果没有条件匹配，返回第一个边
        return edges[0].target_node_id
    
    async def _complete_instance(self, instance: WorkflowInstance) -> None:
        """完成实例"""
        # 从运行队列移除
        if instance.instance_id in self.running_instances:
            del self.running_instances[instance.instance_id]
        
        # 添加到已完成队列
        self._add_to_completed(instance)
        
        # 通知监听器
        if instance.context.status == WorkflowStatus.COMPLETED:
            for listener in self.listeners:
                try:
                    await listener.on_workflow_completed(instance)
                except Exception:
                    pass
        
        # 更新统计
        self.stats["total_executed"] += 1
        if instance.context.status == WorkflowStatus.COMPLETED:
            self.stats["total_completed"] += 1
        elif instance.context.status == WorkflowStatus.FAILED:
            self.stats["total_failed"] += 1
        
        # 更新平均执行时间
        duration = instance.context.get_execution_duration()
        if duration:
            total_time = self.stats["average_execution_time"] * (self.stats["total_executed"] - 1)
            self.stats["average_execution_time"] = (total_time + duration) / self.stats["total_executed"]
    
    def _find_instance(self, instance_id: str) -> Optional[WorkflowInstance]:
        """查找实例"""
        # 在运行队列中查找
        if instance_id in self.running_instances:
            return self.running_instances[instance_id]
        
        # 在待执行队列中查找
        for instance in self.pending_queue:
            if instance.instance_id == instance_id:
                return instance
        
        # 在调度队列中查找
        for instance in self.scheduled_queue:
            if instance.instance_id == instance_id:
                return instance
        
        # 在已完成队列中查找
        if instance_id in self.completed_instances:
            return self.completed_instances[instance_id]
        
        return None
    
    def _remove_from_queues(self, instance: WorkflowInstance) -> None:
        """从队列中移除实例"""
        if instance in self.pending_queue:
            self.pending_queue.remove(instance)
        
        if instance in self.scheduled_queue:
            self.scheduled_queue.remove(instance)
    
    def _add_to_completed(self, instance: WorkflowInstance) -> None:
        """添加到已完成队列"""
        self.completed_instances[instance.instance_id] = instance
        
        # 限制已完成实例数量
        if len(self.completed_instances) > self._max_completed_instances:
            # 移除最旧的实例
            oldest_instance_id = min(
                self.completed_instances.keys(),
                key=lambda x: self.completed_instances[x].context.completed_at or datetime.min
            )
            del self.completed_instances[oldest_instance_id]